﻿/*
 * Copyright © 2020, Wuxi Safover Intelligent Technology Co., Ltd. All rights reserved.
 * 
 * 无锡安永智能科技有限公司版权所有，未经许可，不得用于商业用途
 * 
 * Visit: https://www.safover.com/ 
 */

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Safover.LidarCollector.Extensions;
using Safover.LidarCollector.Config;
using Safover.Lidar.DataContract;

namespace Safover.LidarCollector.Managers
{
    /// <summary>
    /// ZK 版本的文件存储格式
    /// </summary>
    public class V1LidarPacketFileSaver : LidarPacketFileSaver
    {
        private const string timeFormat = "yyyyMMddHHmmss";

        public override void Save(LidarRawFrame frame)
        {
            var localStartTime = TimeUtils.UtcTimestamp2BeiJingDateTime(frame.UtcStartTimestamp);

            var path = GetPath(frame);

            if (!Directory.Exists(path))
            {
                _ = Directory.CreateDirectory(path);
            }
           
            var time = localStartTime.ToString(timeFormat);
            var fullName = Path.Combine(path, $"{frame.StationAbbreviation}{time}.{fileExtension}");

            using (FileStream fs = File.Create(fullName))
            {
                var firstLine = $"{frame.StationAbbreviation}{time}.{fileExtension}{Environment.NewLine}";

                var tempBytes = Encoding.ASCII.GetBytes(firstLine);
                fs.Write(tempBytes, 0, tempBytes.Length);

                var localEndTime = TimeUtils.UtcTimestamp2BeiJingDateTime(frame.UtcEndTimestamp);

                var secondLine = $"{frame.StationAbbreviation} {localStartTime:MM/dd/yyyy HH:mm:ss} {localEndTime:MM/dd/yyyy HH:mm:ss} " +
                    $"E:{frame.Longitude} N:{frame.Latitude} {frame.Altitude} {frame.RollAngle} {frame.PitchAngle} {frame.HeadingAngle} {frame.HorizontalAngle} {frame.VerticalAngle} 0 0{Environment.NewLine}";

                secondLine = secondLine.Replace('-', '/');
                tempBytes = Encoding.ASCII.GetBytes(secondLine);
                fs.Write(tempBytes, 0, tempBytes.Length);

                // TODO: 
                var thirdLine = $"5000 5000{Environment.NewLine}";

                tempBytes = Encoding.ASCII.GetBytes(thirdLine);
                fs.Write(tempBytes, 0, tempBytes.Length);

                fs.WriteByte((byte)'\r');
                fs.WriteByte((byte)'\n');
                fs.WriteByte((byte)'\r');
                fs.WriteByte((byte)'\n');

                foreach (LidarRawChannel c in frame.Channels)
                {
                    var chnl = $"{c.ChannelId} {c.SamplingDepth} {c.SpatialResolution} {c.ChannelName} {c.StoreBitNumber} {c.CumulativePulses} {c.PulseFrequency}{Environment.NewLine}";

                    var chnlInBytes = Encoding.ASCII.GetBytes(chnl);
                    fs.Write(chnlInBytes, 0, chnlInBytes.Length);
                }

                var allChannels = new List<byte>();

                foreach (var channel in frame.Channels)
                {
                    foreach (var adData in channel.Data)
                    {
                        var bytes = BitConverter.GetBytes(Convert.ToInt64(adData));
                        allChannels.AddRange(bytes);
                    }
                }

                fs.Write(allChannels.ToArray(), 0, allChannels.Count);
            }

        }

        private static string GetPath(LidarRawFrame frame)
        {
            var folders = new List<string>
            {
                RuntimeConfigManager.Instance.OthersConfig.DataRootFolder,
            };

            //var utcTime = TimeUtils.Timestamp2UtcTime(frame.UtcStartTimestamp);
            var localTime = TimeUtils.UtcTimestamp2BeiJingDateTime(frame.UtcStartTimestamp);

            // 第二级根存储文件夹名称
            string secondRootFolder;

            string year = localTime.Year.ToString();
            string month = localTime.Month.ToString();

            // 最低级采集周期文件夹名称
            var lastFolder = string.Empty;
            var lastFolderTime = TimeUtils.UtcTimestamp2BeiJingDateTime(frame.UtcPeriodicScanStartTimestamp).ToString(timeFormat);

            switch (frame.LidarScanMode)
            {
                case LidarScanMode.Fixed:
                    {
                        secondRootFolder = "T_STILL";
                    }
                    break;
                case LidarScanMode.Horizontal:
                    {
                        secondRootFolder = "H_SCAN";
                        lastFolder = $"H_SCAN{frame.StartAngle}_{frame.EndAngle}_{frame.VerticalAngle}_{lastFolderTime}";
                    }
                    break;
                case LidarScanMode.Vertical:
                    {
                        secondRootFolder = "V_SCAN";
                        lastFolder = $"V_SCAN{frame.StartAngle}_{frame.EndAngle}_{frame.HorizontalAngle}_{lastFolderTime}";
                    }
                    break;
                case LidarScanMode.Underway:
                    {
                        secondRootFolder = "VEHICLE";
                        lastFolder = $"VEHICLE_{frame.VerticalAngle}_{frame.HorizontalAngle}_{lastFolderTime}";
                    }
                    break;
                default:
                    throw new InvalidOperationException($"{frame.LidarScanMode}: failed to create raw data save path.");
            }

            if (!string.IsNullOrEmpty(secondRootFolder))
            {
                folders.Add(secondRootFolder);
            }

            if (!string.IsNullOrEmpty(year))
            {
                folders.Add(year);
            }

            if (!string.IsNullOrEmpty(month))
            {
                folders.Add(month);
            }


            if (!string.IsNullOrEmpty(lastFolder))
            {
                folders.Add(lastFolder);
            }

            var fullName = Path.Combine(folders.ToArray());

            return fullName;
        }
    }
}
